home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-wos-src / pasm / support.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  7KB  |  291 lines

  1. /* $VER: pasm support.c V1.2 (21.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (21.10.98) phx
  16.  *        strncmpnc() compares first n chars of two strings non-case-sensitive.
  17.  * v1.1d  (27.09.98) phx
  18.  *        fopen() uses binary mode "b" for windoze/msdog compatibility.
  19.  * v0.5   (12.10.97) phx
  20.  *        lower_case(), converts a whole string to lower case.
  21.  *        try_mapfile() adds a '\n'-byte to every file it reads.
  22.  * v0.4   (28.06.97) phx
  23.  *        remnode(), removes a node from a list.
  24.  *        mapfile() automatically adds '/' to an include path.
  25.  * v0.3   (26.03.97)
  26.  *        Little to big endian conversion routine - l2bh(), l2bw().
  27.  * v0.2   (25.03.97) phx
  28.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  29.  *        or ELF output format may be selected. ELF is default for all
  30.  *        currently supported platforms. PPCasm supports nine different
  31.  *        relocation types (there are much more...).
  32.  *        Compiles and works also under NetBSD/amiga (68k).
  33.  *        Changed function declaration to 'new style' in all sources
  34.  *        (to avoid problems with '...' for example).
  35.  *        checkrange() prints a warning message on overflow and no error.
  36.  *        remhead() returns NULL when list is empty.
  37.  * v0.1   (11.03.97) phx
  38.  *        First test version with all PowerPC instructions and most
  39.  *        important directives. Only raw, absolute output.
  40.  *        checkrange() size 3 checks for 26-bit values instead 24-bit.
  41.  *        Do we need a special allocation routine for strings?
  42.  * v0.0   (15.02.97) phx
  43.  *        File created.
  44.  */
  45.  
  46.  
  47. #define SUPPORT_C
  48. #include "ppcasm.h"
  49.  
  50.  
  51. void *alloc(size_t);
  52. void *alloczero(size_t);
  53. char *allocstring(char *);
  54. void initlist(struct list *);
  55. void addtail(struct list *,struct node *);
  56. struct node *remhead(struct list *);
  57. char *mapfile(struct GlobalVars *,char *);
  58. void checkrange(uint32,int,bool);
  59. #ifdef LITTLEENDIAN
  60. uint16 l2bh(uint16);
  61. uint32 l2bw(uint32);
  62. #endif
  63.  
  64. static char *try_mapfile(char *);
  65. static size_t filesize(FILE *,char *);
  66.  
  67.  
  68.  
  69. void *alloc(size_t size)
  70. /* allocate memory and print error message if not enough available */
  71. {
  72.   void *p;
  73.  
  74.   if (!size)
  75.     size = 1;
  76.   if (!(p = malloc(size)))
  77.     error(1);  /* out of memory */
  78.   return (p);
  79. }
  80.  
  81.  
  82. void *alloczero(size_t size)
  83. /* same as alloc() but zeroes the allocated memory */
  84. {
  85.   void *p = alloc(size);
  86.  
  87.   memset(p,0,size);
  88.   return (p);
  89. }
  90.  
  91.  
  92. char *allocstring(char *s)
  93. /* allocate space for a single string */
  94. /* @@@ this should be improved by some kind of string buffer */
  95. {
  96.   char *p = alloc(strlen(s)+1);
  97.  
  98.   strcpy(p,s);
  99.   return (p);
  100. }
  101.  
  102.  
  103. void initlist(struct list *l)
  104. /* initializes a list structure */
  105. {
  106.   l->first = (struct node *)&l->dummy;
  107.   l->dummy = NULL;
  108.   l->last = (struct node *)&l->first;
  109. }
  110.  
  111.  
  112. void addtail(struct list *l,struct node *n)
  113. /* add node as last element of list */
  114. {
  115.   struct node *ln = l->last;
  116.  
  117.   n->next = ln->next;
  118.   ln->next = n;
  119.   n->pred = ln;
  120.   l->last = n;
  121. }
  122.  
  123.  
  124. struct node *remhead(struct list *l)
  125. /* remove first node in list and return a pointer to it */
  126. {
  127.   struct node *n = l->first;
  128.  
  129.   if (n->next) {
  130.     l->first = n->next;
  131.     n->next->pred = n->pred;
  132.     return (n);
  133.   }
  134.   return (NULL);
  135. }
  136.  
  137.  
  138. struct node *remnode(struct node *n)
  139. /* remove a node from a list */
  140. {
  141.   n->next->pred = n->pred;
  142.   n->pred->next = n->next;
  143.   return (n);
  144. }
  145.  
  146.  
  147. char *mapfile(struct GlobalVars *gv,char *name)
  148. /* map a complete file into memory and return its address */
  149. /* the file's length is returned in *(p-sizeof(size_t)) */
  150. /* all defined paths will be searched for the file, before aborting */
  151. {
  152.   char *p;
  153.   int i;
  154.   size_t l;
  155.   char full_name[FNAMEBUFSIZE];
  156.  
  157.   if (p = try_mapfile(name))
  158.     return (p);
  159.   for (i=0; i<MAX_INCPATHS; i++) {
  160.     if (gv->incpaths[i]) {
  161.       strncpy(full_name,gv->incpaths[i],FNAMEBUFSIZE-1);
  162.       l = strlen(gv->incpaths[i]);
  163.       if (l < (FNAMEBUFSIZE-2)) {
  164.         if (full_name[l-1]!='/' && full_name[l-1]!=':')
  165.           full_name[l++] = '/';
  166.         strncat(full_name,name,(FNAMEBUFSIZE-1)-l);
  167.         if (p = try_mapfile(full_name))
  168.           return (p);
  169.       }
  170.     }
  171.   }
  172.   error(6,name);  /* can't open file */
  173. }
  174.  
  175.  
  176. static char *try_mapfile(char *name)
  177. {
  178.   FILE *fp;
  179.   char *p=NULL;
  180.   size_t fsiz;
  181.  
  182.   if (fp = fopen(name,"rb")) {
  183.     fsiz = filesize(fp,name);
  184.     p = alloc(fsiz+1+sizeof(size_t));
  185.     *(size_t *)p = fsiz + 1;  /* store file size before the text starts */
  186.     p += sizeof(size_t);
  187.     if (fread(p,1,fsiz,fp) != fsiz) {
  188.       fclose(fp);
  189.       error(5,name);  /* read error */
  190.     }
  191.     fclose(fp);
  192.     *(p+fsiz) = '\n';  /* always have a '\n'-byte at the end */
  193.   }
  194.   return (p);
  195. }
  196.  
  197.  
  198. static size_t filesize(FILE *fp,char *name)
  199. {
  200.   /* somebody knows a better way to determine file size in ANSI C? */
  201.   long oldpos,size;
  202.  
  203.   if ((oldpos = ftell(fp)) >= 0)
  204.     if (fseek(fp,0,SEEK_END) >= 0)
  205.       if ((size = ftell(fp)) >= 0)
  206.         if (fseek(fp,oldpos,SEEK_SET) >= 0)
  207.           return ((size_t)size);
  208.   fclose(fp);
  209.   error(5,name);  /* read error - doesn't return */
  210. }
  211.  
  212.  
  213. void checkrange(uint32 val,int size,bool sign)
  214. /* checks if an integer value is in range, size=3 means 26-bit (B-instr.) */
  215. {
  216.   int sval;
  217.  
  218.   if (sign) {
  219.     sval = (int)val;
  220.     switch (size) {
  221.       case 1:
  222.         if (sval>0x7f || sval<-0x80)
  223.           error(30,8);  /* immediate operand doesn't fit into 8 bits */
  224.         break;
  225.       case 2:
  226.         if (sval>0x7fff || sval<-0x8000)
  227.           error(30,16);
  228.         break;
  229.       case 3:
  230.         if (sval>0x1ffffff || sval<-0x2000000)
  231.           error(30,24);
  232.         break;
  233.     }
  234.   }
  235.   else {
  236.     switch (size) {
  237.       case 1:
  238.         if (val>0xff)
  239.           error(30,8);
  240.         break;
  241.       case 2:
  242.         if (val>0xffff)
  243.           error(30,16);
  244.         break;
  245.       case 3:
  246.         if (val>0x3ffffff)
  247.           error(30,24);
  248.         break;
  249.     }
  250.   }
  251. }
  252.  
  253.  
  254. void lower_case(char *s)
  255. /* convert a whole string to lower case */
  256. {
  257.   unsigned char c;
  258.  
  259.   while (c = (unsigned char)*s)
  260.     *s++ = tolower((int)c);
  261. }
  262.  
  263.  
  264. int strncmpnc(char *s1,char *s2,int n)
  265. /* compares two strings non-case-sensitive */
  266. {
  267.   int c;
  268.  
  269.   while (n--) {
  270.     if (c = toupper((unsigned char)*s1++) - toupper((unsigned char)*s2++))
  271.       return (c);
  272.   }
  273.   return (0);
  274. }
  275.  
  276.  
  277. #ifdef LITTLEENDIAN
  278. uint16 l2bh(uint16 x)
  279. /* little endian half word conversion */
  280. {
  281.   return ECH(x);
  282. }
  283.  
  284.  
  285. uint32 l2bw(uint32 x)
  286. /* little endian word conversion */
  287. {
  288.   return ECW(x);
  289. }
  290. #endif
  291.